package com.usian.wemedia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.usian.common.dtos.PageResult;
import com.usian.common.enums.AppHttpCodeEnum;
import com.usian.common.exception.LeadException;
import com.usian.common.threadlocal.UserThreadLocalUtils;
import com.usian.common.util.BeanHelper;
import com.usian.common.util.JsonUtils;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.media.dtos.WmNewsDto;
import com.usian.model.media.dtos.WmNewsPageReqDto;
import com.usian.model.media.dtos.WmNewsResultDTO;
import com.usian.model.media.dtos.WmUserDto;
import com.usian.wemedia.entity.WmMaterial;
import com.usian.wemedia.entity.WmNews;
import com.usian.wemedia.mapper.WmNewsMapper;
import com.usian.wemedia.service.IWmMaterialService;
import com.usian.wemedia.service.IWmNewsMaterialService;
import com.usian.wemedia.service.IWmNewsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.usian.common.constants.message.NewsAutoScanConstants.WM_NEWS_AUTO_SCAN_TOPIC;
import static com.usian.common.constants.message.WmNewsUpDownConstants.WM_NEWS_UP_OR_DOWN_TOPIC;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author usian
 * @since 2022-10-04
 */
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements IWmNewsService {

    @Override
    public PageResult<WmNewsDto> findByPage(WmNewsPageReqDto dto) {
        //1、参数校验
        if(dto==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //2、从线程中获取用户id
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3、封装分页条件
        Page<WmNews> page = new Page<>(dto.getPage(),dto.getSize());

        //4、封装查询条件
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        //4.1、查询当前用户编辑的文章（userId)
        queryWrapper.lambda().eq(WmNews::getWmUserId,userId);
        //4.2、根据文章状态查询
        Integer status = dto.getStatus();
        if(status!=null && status!=-1){
            //条件是status==1待审核状态  待人工审核3和待自动审核1
            if(status==1){
                queryWrapper.lambda().in(WmNews::getStatus,new Integer[]{1,3});
            }else if(status==4){
                //审核通过   人工审核通过4、自动审核通过8、已发布9
                queryWrapper.lambda().in(WmNews::getStatus,new Integer[]{4,8,9});
            }else{
                //审核失败、存入草稿
                queryWrapper.lambda().eq(WmNews::getStatus,status);
            }
        }

        //4.3、根据关键字条件查询
        String keyword = dto.getKeyword();
        if(StringUtils.isNotBlank(keyword)){
            queryWrapper.lambda().like(WmNews::getTitle,keyword);
        }

        //4.4、根据频道条件查询
        Integer channelId = dto.getChannelId();
        if (channelId!=null) {
            queryWrapper.lambda().eq(WmNews::getChannelId,channelId);
        }

        //4.5、根据发布时间查询
        Date beginPubDate = dto.getBeginPubDate();
        if(beginPubDate!=null){
            //发布时间大于等于开始时间
            queryWrapper.lambda().ge(WmNews::getPublishTime,beginPubDate);
        }
        Date endPubDate = dto.getEndPubDate();
        if(endPubDate!=null){
            //发布时间小于等于结束时间
            queryWrapper.lambda().le(WmNews::getPublishTime,endPubDate);
        }

        //5、执行查询，封装查询结果
        IPage<WmNews> iPage = this.page(page, queryWrapper);
        List<WmNews> records = iPage.getRecords();
        if(CollectionUtils.isEmpty(records)){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        List<WmNewsDto> dtoList = BeanHelper.copyWithCollection(records, WmNewsDto.class);

        return new PageResult<>(dto.getPage(),dto.getSize(),iPage.getTotal(),dtoList);
    }

    @Autowired
    private IWmNewsMaterialService wmNewsMaterialService;

    @Autowired
    private IWmMaterialService wmMaterialService;

    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;


    @Override
    public void saveNews(WmNewsDto dto) {
        //1、参数校验
        if(dto==null || StringUtils.isBlank(dto.getTitle()) || StringUtils.isBlank(dto.getContent())){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2、从先当前线程中获取用户id
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3、处理数据
        //对象转换
        WmNews wmNews = BeanHelper.copyProperties(dto, WmNews.class);
        //判断是新增还是修改操作
        if(wmNews.getId()==null){
            //新增
            wmNews.setCreatedTime(new Date());
            wmNews.setWmUserId(userId);
        }
        //判断是否存入草稿
        if(!dto.getDraft()){
            //不是存入草稿，需要记录提交时间
            wmNews.setSubmitedTime(new Date());
        }

        //封面图片，以逗号分隔
        List<String> imagesList = dto.getImages();
        if(!CollectionUtils.isEmpty(imagesList)){
            String images = imagesList.stream().collect(Collectors.joining(","));
            wmNews.setImages(images);
        }

        //判断是否是修改操作
        if(wmNews.getId()!=null){
            //修改操作，删除文章和素材关联关系
            wmNewsMaterialService.deleteByNewsId(wmNews.getId());
        }

        //执行保存或修改操作
        boolean b = this.saveOrUpdate(wmNews);
        if(!b){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"保存或修改自媒体文章失败");
        }

        //解析正文（json格式字符串）
        String content = dto.getContent();
        List<Map<String, String>> mapList = JsonUtils.nativeRead(content, new TypeReference<List<Map<String, String>>>() {
        });
        //获取正文中的图片地址集合
        List<String> contentImageList = parseImageUrl(mapList);
        List<Integer> materialIds = null;
        if(!CollectionUtils.isEmpty(contentImageList)){
            //获取图片地址关联的素材id集合
            materialIds = getMaterialIds(userId,contentImageList);
            //批量保存素材和文章的关联关系
            wmNewsMaterialService.saveInfoBatch(wmNews.getId(),materialIds,0);
        }

        //设置封面图片关联素材
        if(!CollectionUtils.isEmpty(imagesList)){
            //获取图片地址关联的素材id集合
            materialIds = getMaterialIds(userId,imagesList);
            //批量保存素材和文章的关联关系
            wmNewsMaterialService.saveInfoBatch(wmNews.getId(),materialIds,1);
        }

        //不是保存草稿操作，生产文章审核的消息,内容是自媒体新闻id
        if(!dto.getDraft()){
            kafkaTemplate.send(WM_NEWS_AUTO_SCAN_TOPIC,wmNews.getId().toString());
        }

    }

    @Override
    public void deleteNews(Integer id) {
        //参数校验
        if(id==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //获取用户id
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId==null) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }

        //查询自媒体文章，获取相关状态
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getWmUserId,userId).eq(WmNews::getId,id);
        WmNews wmNews = this.getOne(queryWrapper);
        if(wmNews==null){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"自媒体文章不存在");
        }
        if(wmNews.getStatus()==9 && wmNews.getEnable()){
            //自媒体文章已发布，而且上架了，不能删除
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"自媒体文章已发布，而且上架了，不能删除");
        }
        //如果自媒体文章是未发布状态且未上架，可以删除
        //删除自媒体文章和关联的素材关系
        wmNewsMaterialService.deleteByNewsId(id);
        //删除文章
        boolean b = removeById(id);
        if (!b) {
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"删除自媒体文章失败");
        }
    }

    @Override
    public void downOrUp(WmNewsDto dto) {
        //参数校验
        if(dto==null || dto.getId()==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if(dto.getEnable()==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE,"上下架状态不能为空");
        }

        //获取用户id
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId==null) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //查询自媒体文章，获取相关状态
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getId,dto.getId()).eq(WmNews::getWmUserId,userId);
        WmNews wmNews = this.getOne(queryWrapper);
        if (wmNews==null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"自媒体文章数据不存在");
        }
        //如果自媒体文章不是发布状态，不能上下架
        if(wmNews.getStatus()!=9){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"自媒体文章不是发布状态，不能上下架");
        }
        //更新自媒体文章上下架状态
        WmNews wmNews1= new WmNews();
        wmNews1.setId(wmNews.getId());
        wmNews1.setEnable(dto.getEnable());
        boolean b = this.updateById(wmNews1);
        if(!b){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"自媒体文章上下架失败");
        }

        //生产消息，同步App文章上下架状态
        Map<String,Integer> map = new HashMap<>();
        map.put("wmNewsId",wmNews.getId());
        map.put("enable",dto.getEnable()?1:0);
        kafkaTemplate.send(WM_NEWS_UP_OR_DOWN_TOPIC,JsonUtils.toString(map));
    }

    @Override
    public List<Integer> findWmNewsIds() {
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getStatus, WmNewsResultDTO.Status.SUCCESS.getCode()).lt(WmNews::getPublishTime,new Date());
        List<WmNews> wmNewsList = this.list(queryWrapper);
        if(CollectionUtils.isEmpty(wmNewsList)){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"审核通过待发布的自媒体文章不存在");
        }
        List<Integer> list = wmNewsList.stream().map(WmNews::getId).collect(Collectors.toList());
        return list;
    }

    @Override
    public PageResult<WmNewsResultDTO> findWmNewsPage(NewsAuthDto dto) {
        if(dto==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //封装分页条件
        Page<WmNews> page = new Page<>(dto.getPage(),dto.getSize());

        //判断标题参数是否存在
        /*String title = dto.getTitle();
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        if(StringUtils.isNotBlank(title)){
            queryWrapper.lambda().like(WmNews::getTitle,title);
        }
        //执行查询
        IPage<WmNews> iPage = this.page(page, queryWrapper);*/

        IPage<WmNewsResultDTO> iPage = this.getBaseMapper().slectWmNewsByPage(page, dto);
        List<WmNewsResultDTO> records = iPage.getRecords();
        if(CollectionUtils.isEmpty(records)){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        return new PageResult<>(dto.getPage(),dto.getSize(),iPage.getTotal(),records);
    }

    /**
     * 获取图片地址关联的素材id集合
     * @param userId
     * @param contentImageList
     * @return
     */
    private List<Integer> getMaterialIds(Integer userId, List<String> contentImageList) {
        //设置查询条件
        QueryWrapper<WmMaterial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmMaterial::getUserId,userId).in(WmMaterial::getUrl,contentImageList);
        List<WmMaterial> materialList = wmMaterialService.list(queryWrapper);
        if(CollectionUtils.isEmpty(materialList)){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        List<Integer> materialIds = materialList.stream().map(WmMaterial::getId).collect(Collectors.toList());
        return materialIds;

    }

    /**
     * 获取正文中的图片地址集合
     * @param mapList
     * @return
     */
    private List<String> parseImageUrl(List<Map<String, String>> mapList) {
        //构造存储数据集合
        Set<String> set = new HashSet<>();
        for (Map<String, String> map : mapList) {
            if(map.get("type").equals("image")){
                String image = map.get("value");
                //去除正文中引用的重复图片地址
                set.add(image);
            }
        }
        //构建List集合存储数据
        List<String> list = new ArrayList<>();
        list.addAll(set);
        return list;

    }
}
